package com.leepood.pihomecontrol.socket;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * This is the network bridge which can send & receive message
 * 
 * @author leepood
 * 
 */
public class Client {

	private volatile boolean isRun = false;

	/**
	 * Queue of send data
	 */
	private ConcurrentLinkedQueue<byte[]> sendDatas = new ConcurrentLinkedQueue<byte[]>();

	/**
	 * Queue of receive data
	 */
	private ConcurrentLinkedQueue<byte[]> receiveDatas = new ConcurrentLinkedQueue<byte[]>();

	/**
	 * default port
	 */
	public static final int DEFAULT_PORT = 8081;

	/**
	 * server ip
	 */
	public static final String DEFAULT_SERVER = "192.168.1.1";

	private int mPort = DEFAULT_PORT;

	private String serverIp = DEFAULT_SERVER;

	private Socket mClientSocket = null;

	private static final int RE_CONNECT_TIMES = 3;

	public Client(String ip, int port) {
		mPort = port;
		serverIp = ip;
	}

	/**
	 * Initial socket
	 * 
	 * @return
	 */
	public boolean connect() {
		try {
			mClientSocket = new Socket(serverIp, mPort);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	public void startClient() {
		// Start the send thread & receive thread
		isRun = true;
		new SendThread(mClientSocket).start();
		new ReceiveThread(mClientSocket).start();
	}

	public void stop() {
		try {
			isRun = false;
			mClientSocket.close();
			mClientSocket = null;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public void sendMsg(byte[] data) {
		sendDatas.add(data);
	}

	/**
	 * 发送消息线程
	 * 
	 * @author leepood
	 * 
	 */
	class SendThread extends Thread {

		private Socket socket;

		private OutputStream os = null;

		public SendThread(Socket mSocket) {
			setName("SendThread");
			socket = mSocket;

		}

		@Override
		public void run() {

			try {
				os = socket.getOutputStream();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return;
			}
			// A loop to send data
			while (isRun) {
				byte[] data2Send = sendDatas.poll();

				if (null != data2Send) {
					try {
						os.write(data2Send);
					} catch (IOException e) {
						e.printStackTrace();
					}
				}

				try {
					sleep(20);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 收消息线程
	 * 
	 * @author leepood
	 * 
	 */
	class ReceiveThread extends Thread {

		private Socket socket;

		private InputStream is = null;

		public ReceiveThread(Socket mSocket) {
			setName("ReceiveThread");
			socket = mSocket;
		}

		@Override
		public void run() {
			try {
				is = socket.getInputStream();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return;
			}

			while (isRun) {
				ByteArrayOutputStream baos = null;
				int length = -1;
				byte[] buffer = new byte[512];

				try {
					baos = new ByteArrayOutputStream();
					while ((length = is.read(buffer)) != -1) {
						baos.write(buffer, 0, length);
					}
					byte[] result = baos.toByteArray();
					receiveDatas.add(result);
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} finally {
					try {
						if (null != baos) {
							baos.close();
							baos = null;
						}
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}

				try {
					sleep(20);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}

}
